package org.neurone.userspace.dao.impl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.neurone.domain.Application;
import org.neurone.domain.UserDetailInfo;
import org.neurone.domain.UserInfo;
import org.neurone.domain.UserConfig;
import org.neurone.domain.alter.UserInfoAlter;
import org.neurone.domain.persistence.ApplicationPersistence;
import org.neurone.domain.persistence.UserConfigPersistence;
import org.neurone.domain.persistence.UserDetailInfoPersistence;
import org.neurone.domain.persistence.UserInfoPersistence;
import org.neurone.exception.PersistenceEntityNotFound;
import org.neurone.userspace.dao.ApplicationDao;
import org.neurone.userspace.dao.UserInfoDao;
import org.neurone.util.criteria.Criteria;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

public class UserInfoDaoImpl extends BaseDaoHibernate implements UserInfoDao {
	private ApplicationDao applicationDao;
	
	
	
	public ApplicationDao getApplicationDao() {
		return applicationDao;
	}

	public void setApplicationDao(ApplicationDao applicationDao) {
		this.applicationDao = applicationDao;
	}

	@Override
	public void deleteUser(Long userID) {
		UserInfoPersistence uip = find(userID);
		getHibernateTemplate().delete(uip);
	}

	@Override
	public UserInfoPersistence find(Long userID) {
		return (UserInfoPersistence)getHibernateTemplate().load(UserInfoPersistence.class, userID);
	}

	@Override
	public Long newUser(UserInfo userInfo) {
		UserInfoPersistence uip = new UserInfoPersistence();
		fillUserInfo(userInfo, uip);
		getHibernateTemplate().saveOrUpdate(uip);
		return uip.getUserID();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<UserInfo> search(final Criteria terms, final int pageSize, final int pageIndex) {
		List<UserInfo> list = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
			throws HibernateException, SQLException {
				String termString = "";
				if(terms != null)
				{
					termString = " where "+terms.getSQLCriteria();
				}
				Query query = session.createQuery("from UserInfoPersistence as userInfoPersistence "+termString );
				//query.setFirstResult(pageSize *pageIndex);
				//query.setMaxResults(pageSize);
				List<UserInfo> list = query.list();
				return list;
			}
		});
		return list;

	}

	@Override
	public void update(UserInfo userInfo) {
		UserInfoPersistence uip = find(userInfo.getUserID());
		fillUserInfo(userInfo, uip);
		getHibernateTemplate().update(uip);
	}

	@Override
	public void updateConfig(Long UserID, UserConfig userConfig) {
		UserConfigPersistence userConfigOld = (UserConfigPersistence)find(UserID).getUserConfig();
		if(userConfigOld == null)
		{
			userConfigOld = new UserConfigPersistence();
		}
		
		userConfigOld.setUserConfigID(userConfig.getUserConfigID());
		userConfigOld.setMessage2EmailNotify(userConfig.isMessage2EmailNotify());
		
		getHibernateTemplate().saveOrUpdate(userConfigOld);
	}

	@Override
	public UserConfig getUserConfig(UserInfo userInfo) {
		return userInfo.getUserConfig();
	}

	private UserInfoPersistence fillUserInfo(UserInfo source, UserInfoPersistence uip)
	{
		uip.setEmail(source.getEmail());
		uip.setImage(source.getImage());
		uip.setPasswd(source.getPasswd());
		uip.setRealName(source.getRealName());
		uip.setStatus(source.getStatus());
		uip.setUserName(source.getUserName());
		uip.setUserNick(source.getUserNick());
		
		return uip;
	}

	@Override
	public void assignApplication(final Long userID, final Long applicationID) {
		getHibernateTemplate().execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				UserInfoPersistence uip = (UserInfoPersistence) session.load(UserInfoPersistence.class, userID);
				ApplicationPersistence ap = (ApplicationPersistence)session.load(ApplicationPersistence.class, applicationID);
				
				Set<Application> appSet = uip.getAssignedApplicationList();
				appSet.add(ap);
				
				getHibernateTemplate().update(uip);
				return uip;
			}
		});
	}

	@Override
	public void unassignApplication(final Long userID, final Long applicationID) {
		getHibernateTemplate().execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				UserInfoPersistence uip = (UserInfoPersistence) session.load(UserInfoPersistence.class, userID);
				ApplicationPersistence ap = (ApplicationPersistence)session.load(ApplicationPersistence.class, applicationID);
				
				Set<Application> appSet = uip.getAssignedApplicationList();
				appSet.remove(ap);
				
				getHibernateTemplate().update(uip);
				return uip;
			}
		});
	}

	@Override
	public List<Application> listAssignedApplication(final Long userID) {
		HibernateTemplate god = getHibernateTemplate();
		
		//由于关联列表使用了lazy加载，所以需要在统一Session下读取列表
		return (List<Application>)god.execute(new HibernateCallback(){

			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				
				UserInfoPersistence u= (UserInfoPersistence)session.load(UserInfoPersistence.class, userID);
				
				List<Application> ual = new ArrayList<Application>();
				for (Application ap : u.getAssignedApplicationList()) {
					ual.add(ap);
				}
				
				return ual;
			}
		});
	}
}
